import { ref, computed, watch, nextTick,getCurrentInstance } from 'vue';
import type { Ref } from 'vue';
import type { hooksParam, CommonState } from '.';
import { getPx } from '../../../libs/utils/_utils';
import { sleep,getRect } from '../../../libs/utils';
import { Enum } from '../env';
import { delay } from '../utils';

const useVirtual = (ctx: ReturnType<typeof getCurrentInstance>,option: Ref<hooksParam>, emit: ReturnType<typeof defineEmits>,commonState: CommonState,oldScrollTop: Ref<number>,) => {
	const virtualPageHeight = ref(0);
	const virtualCellHeight = ref(0);
	let virtualScrollTimeStamp = 0;

	const virtualPlaceholderTopHeight = ref(0);
	const virtualPlaceholderBottomHeight = ref(0);
	let virtualTopRangeIndex = 0;
	let virtualBottomRangeIndex = 0;
	let lastVirtualTopRangeIndex = 0;
	let lastVirtualBottomRangeIndex = 0;

	const virtualHeightCacheList = ref<{
		height: number
		lastTotalHeight:number,
		totalHeight: number
	}[]>([]);

	let getCellHeightRetryCount = {
		fixed: 0,
		dynamic: 0
	};

	let pagingOrgTop = -1;
	let updateVirtualListFromDataChange = false;

	const finalUseVirtualList = computed(() => option.value.useVirtualList && !option.value.usePageScroll)
	const finalVirtualPageHeight = computed(() =>{
		return virtualPageHeight.value > 0 ? virtualPageHeight.value : (commonState.systemInfo.windowHeight || 0);
	})
	const finalFixedCellHeight = computed(()=> {
		return getPx(option.value.fixedCellHeight!);
	})
	const virtualRangePageHeight = computed(() =>{
		return finalVirtualPageHeight.value * (option.value.preloadPage as number);
	})
	const virtualScrollDisTimeStamp = computed(() => {
		return 1000 / (option.value.virtualScrollFps as number);
	})
	
	
		// 在使用动态高度虚拟列表时，若在列表数组中需要插入某个item，需要调用此方法；item:需要插入的item，index:插入的cell位置，若index为2，则插入的item在原list的index=1之后，index从0开始
	const doInsertVirtualListItem = (item:any, index:number) => {
			if (option.value.cellHeightMode !== Enum.CellHeightMode.Fixed) return;
			
		
			const cellIndexKey = option.value.virtualItemIdKey!;
			
			nextTick(async () => {
				let retryCount = 0;
				while (retryCount <= 10) {
					await sleep(100);
					
					const cellNode = await getRect(ctx,`#${cellIndexKey}${index}`);
					// 如果获取当前cell的节点信息失败，则重试（不超过10次）
					if (!cellNode) {
						retryCount ++;
						continue;
					} 
					
					const currentHeight = cellNode?.height || 0;
					const lastHeightCache = virtualHeightCacheList.value[index - 1];
					const lastTotalHeight = lastHeightCache ? lastHeightCache.totalHeight : 0;
					// 在缓存的cell高度数组中，插入此cell高度信息
					virtualHeightCacheList.value.splice(index, 0, {
						height: currentHeight,
						lastTotalHeight,
						totalHeight: lastTotalHeight + currentHeight
					});
					
					// 从当前index起后续的cell缓存高度的lastTotalHeight和totalHeight需要加上当前cell的高度
					for (let i = index + 1; i < virtualHeightCacheList.value.length; i++) {
						const thisNode = virtualHeightCacheList.value[i];
						thisNode.lastTotalHeight += currentHeight;
						thisNode.totalHeight += currentHeight;
					}
					
					_updateVirtualScroll(oldScrollTop.value);
					break;
				}
			})
		}
		// 在使用动态高度虚拟列表时，手动更新指定cell的缓存高度(当cell高度在初始化之后再次改变时调用)；index:需要更新的cell在列表中的位置，从0开始
		const didUpdateVirtualListCell = (index:number) => {
			if (option.value.cellHeightMode !== Enum.CellHeightMode.Dynamic) return;
			const currentNode = virtualHeightCacheList.value[index];
			nextTick(() => {
				getRect(ctx,`#${option.value.virtualItemIdKey!}{index}`).then(cellNode => {
					// 更新当前cell的高度
					const cellNodeHeight = cellNode?.height || 0;
					const heightDis = cellNodeHeight - currentNode.height;
					currentNode.height = cellNodeHeight;
					currentNode.totalHeight = currentNode.lastTotalHeight + cellNodeHeight;
					
					// 从当前index起后续的cell缓存高度的lastTotalHeight和totalHeight需要加上当前cell变化的高度
					for (let i = index + 1; i < virtualHeightCacheList.value.length; i++) {
						const thisNode = virtualHeightCacheList.value[i];
						thisNode.totalHeight += heightDis;
						thisNode.lastTotalHeight += heightDis;
					}
				});
			})
		}
		// 在使用动态高度虚拟列表时，若删除了列表数组中的某个item，需要调用此方法以更新高度缓存数组；index:删除的cell在列表中的位置，从0开始
		const didDeleteVirtualListCell = (index:number) => {
			if (option.value.cellHeightMode !== Enum.CellHeightMode.Dynamic) return;
			const currentNode = virtualHeightCacheList.value[index];
			// 从当前index起后续的cell缓存高度的lastTotalHeight和totalHeight需要减去当前cell的高度
			for (let i = index + 1; i < virtualHeightCacheList.value.length; i++) {
				const thisNode = virtualHeightCacheList.value[i];
				thisNode.totalHeight -= currentNode.height;
				thisNode.lastTotalHeight -= currentNode.height;
			}
			// 将当前cell的高度信息从高度缓存数组中删除
			virtualHeightCacheList.value.splice(index, 1);
		}
		// 手动触发虚拟列表渲染更新，可用于解决例如修改了虚拟列表数组中元素，但展示未更新的情况
		
		const updateVirtualListRender = (_option?:{
			isFirstPage?:boolean,//是否为第一页
			resetVirtualList?:boolean//是否重置虚拟列表
		}) => {
			// #ifndef APP-NVUE
			if (finalUseVirtualList.value) {
				updateVirtualListFromDataChange = true;
				nextTick(() => {
					getCellHeightRetryCount.fixed = 0;
					if (option.value.virtualListData!.length) {
						option.value.cellHeightMode === Enum.CellHeightMode.Fixed && _option?.isFirstPage && _updateFixedCellHeight()
					} else {
						_resetDynamicListState(_option?.resetVirtualList);
					}
					_updateVirtualScroll(oldScrollTop.value);
				})
			}
			// #endif
		}
		// 初始化虚拟列表
		const _virtualListInit = () => {
			nextTick(() => {
				delay(() => {
					// 获取虚拟列表滚动区域的高度
					getRect(ctx,'.e-scroll-view__super-container__scroll-view').then(node => {
						if (node) {
							pagingOrgTop = node.top||0;
							virtualPageHeight.value = node.height||0;
						}
					});
				});
			})
		}
		// cellHeightMode为fixed时获取第一个cell高度
		const _updateFixedCellHeight = () => {
			if (!finalFixedCellHeight.value) {
				nextTick(() => {
					delay(() => {
						getRect(ctx,`#${option.value.virtualItemIdKey!}0`).then(cellNode => {
							if (!cellNode) {
								if (getCellHeightRetryCount.fixed > 10) return;
								getCellHeightRetryCount.fixed ++;
								// 如果获取第一个cell的节点信息失败，则重试（不超过10次）
								_updateFixedCellHeight();
							} else {
								virtualCellHeight.value = cellNode.height||0;
								_updateVirtualScroll(oldScrollTop.value);
							}
						});
					}, 100, 'updateFixedCellHeightDelay');
				})
			} else {
				virtualCellHeight.value = finalFixedCellHeight.value;
			}
		}
		// cellHeightMode为dynamic时获取每个cell高度
		const _updateDynamicCellHeight = (list:any, dataFrom = 'bottom') => {
			const dataFromTop = dataFrom === 'top';
			const heightCacheList = virtualHeightCacheList.value;
			const currentCacheList = dataFromTop ?  [] : heightCacheList;
			let listTotalHeight = 0;
			nextTick(() => {
				delay(async () => {
					for (let i = 0; i < list.length; i++) {
						const cellNode = await getRect(ctx,`#${option.value.virtualItemIdKey!}${i}`);
						const currentHeight = cellNode?.height|| 0;
						if (!cellNode) {
							if (getCellHeightRetryCount.dynamic <= 10) {
								heightCacheList.splice(heightCacheList.length - i, i);
								getCellHeightRetryCount.dynamic ++;
								// 如果获取当前cell的节点信息失败，则重试（不超过10次）
								_updateDynamicCellHeight(list, dataFrom);
							}
							return;
						} 
						const lastHeightCache = currentCacheList.length ? currentCacheList.slice(-1)[0] : null;
						const lastTotalHeight = lastHeightCache ? lastHeightCache.totalHeight : 0;
						// 缓存当前cell的高度信息：height-当前cell高度；lastTotalHeight-前面所有cell的高度总和；totalHeight-包含当前cell的所有高度总和
						currentCacheList.push({
							height: currentHeight,
							lastTotalHeight,
							totalHeight: lastTotalHeight + currentHeight
						});
						if (dataFromTop) {
							listTotalHeight += currentHeight;
						}
					}
					// 如果数据是从顶部拼接的
					if (dataFromTop && list.length) {
						for (let i = 0; i < heightCacheList.length; i++) {
							// 更新之前所有项的缓存高度，需要加上此次插入的所有cell高度之和（因为是从顶部插入的cell）
							const heightCacheItem = heightCacheList[i];
							heightCacheItem.lastTotalHeight += listTotalHeight;
							heightCacheItem.totalHeight += listTotalHeight;
						}
						virtualHeightCacheList.value = currentCacheList.concat(heightCacheList);
					}
					_updateVirtualScroll(oldScrollTop.value);
				}, 100, 'updateDynamicCellHeightDelay')
			})
		}

		// 更新scroll滚动（虚拟列表滚动时触发）
		const _updateVirtualScroll = (scrollTop:number, scrollDiff = 0) => {
			const currentTimeStamp = new Date().getTime();
			scrollTop === 0 && _resetTopRange();
			if (scrollTop !== 0 && virtualScrollTimeStamp && currentTimeStamp - virtualScrollTimeStamp <= virtualScrollDisTimeStamp.value) {
				return;
			}
			virtualScrollTimeStamp = currentTimeStamp;
			
			
			const cellHeightMode = option.value.cellHeightMode;
			let scrollIndex = 0;
			if (cellHeightMode === Enum.CellHeightMode.Fixed) {
				// 如果是固定高度的虚拟列表
				// 计算当前滚动到的cell的index = scrollTop / 虚拟列表cell的固定高度
				scrollIndex = parseInt(`${scrollTop / virtualCellHeight.value}`) || 0;
				// 更新顶部和底部占位view的高度（为兼容考虑，顶部采用transformY的方式占位)
				_updateFixedTopRangeIndex(scrollIndex);
				_updateFixedBottomRangeIndex(scrollIndex);
			} else if(cellHeightMode === Enum.CellHeightMode.Dynamic) {
				// 如果是不固定高度的虚拟列表
				// 当前滚动的方向
				const scrollDirection = scrollDiff > 0 ? 'top' : 'bottom';
				// 视图区域的高度
				const rangePageHeight = virtualRangePageHeight.value;
				// 顶部视图区域外的高度（顶部不需要渲染而是需要占位部分的高度）
				const topRangePageOffset = scrollTop - rangePageHeight;
				// 底部视图区域外的高度（底部不需要渲染而是需要占位部分的高度）
				const bottomRangePageOffset = scrollTop + finalVirtualPageHeight.value + rangePageHeight;
				
				let _virtualBottomRangeIndex = 0;
				let _virtualPlaceholderBottomHeight = 0;
				let reachedLimitBottom = false;
				const heightCacheList = virtualHeightCacheList.value;
				const lastHeightCache = !!heightCacheList ? heightCacheList.slice(-1)[0] : null;
				
				let startTopRangeIndex = virtualTopRangeIndex;
				// 如果是向底部滚动（顶部占位的高度不断增大，顶部的实际渲染cell数量不断减少）
				if (scrollDirection === 'bottom') {
					// 从顶部视图边缘的cell的位置开始向后查找
					for (let i = startTopRangeIndex; i < heightCacheList.length; i++){
						const heightCacheItem = heightCacheList[i];
						// 如果查找到某个cell对应的totalHeight大于顶部视图区域外的高度，则此cell为顶部视图边缘的cell
						if (heightCacheItem && heightCacheItem.totalHeight > topRangePageOffset) {
							// 记录顶部视图边缘cell的index并更新顶部占位区域的高度并停止继续查找
							virtualTopRangeIndex = i;
							virtualPlaceholderTopHeight.value = heightCacheItem.lastTotalHeight;
							break;
						}
					}
				} else {
					// 如果是向顶部滚动（顶部占位的高度不断减少，顶部的实际渲染cell数量不断增加）
					let topRangeMatched = false;
					// 从顶部视图边缘的cell的位置开始向前查找
					for (let i = startTopRangeIndex; i >= 0; i--){
						const heightCacheItem = heightCacheList[i];
						// 如果查找到某个cell对应的totalHeight小于顶部视图区域外的高度，则此cell为顶部视图边缘的cell
						if (heightCacheItem && heightCacheItem.totalHeight < topRangePageOffset) {
							// 记录顶部视图边缘cell的index并更新顶部占位区域的高度并停止继续查找
							virtualTopRangeIndex = i;
							virtualPlaceholderTopHeight.value = heightCacheItem.lastTotalHeight;
							topRangeMatched = true;
							break;
						}
					}
					// 如果查找不到，则认为顶部占位高度为0了，顶部cell不需要继续复用，重置topRangeIndex和placeholderTopHeight
					!topRangeMatched && _resetTopRange();
				}
				// 从顶部视图边缘的cell的位置开始向后查找
				for (let i = virtualTopRangeIndex; i < heightCacheList.length; i++){
					const heightCacheItem = heightCacheList[i];
					// 如果查找到某个cell对应的totalHeight大于底部视图区域外的高度，则此cell为底部视图边缘的cell
					if (heightCacheItem && heightCacheItem.totalHeight > bottomRangePageOffset) {
						// 记录底部视图边缘cell的index并更新底部占位区域的高度并停止继续查找
						_virtualBottomRangeIndex = i;
						_virtualPlaceholderBottomHeight = lastHeightCache!.totalHeight - heightCacheItem.totalHeight;
						reachedLimitBottom = true;
						break;
					}
				}
				if (!reachedLimitBottom || virtualBottomRangeIndex === 0) {
					virtualBottomRangeIndex = (option.value.virtualListData!).length ? (option.value.virtualListData!).length - 1 : (option.value.virtualListPageSize as number);
					virtualPlaceholderBottomHeight.value = 0;
				} else {
					virtualBottomRangeIndex = _virtualBottomRangeIndex;
					virtualPlaceholderBottomHeight.value = _virtualPlaceholderBottomHeight;
				}
				_updateVirtualList();
			}
		}
		// 更新fixedCell模式下topRangeIndex&placeholderTopHeight
		const _updateFixedTopRangeIndex = (scrollIndex:number) => {
			let _virtualTopRangeIndex = virtualCellHeight.value === 0 ? 0 : scrollIndex - (parseInt(`${finalVirtualPageHeight.value / virtualCellHeight.value}`) || 1) * (option.value.preloadPage as number);
			_virtualTopRangeIndex *= (option.value.virtualListCol as number);
			_virtualTopRangeIndex = Math.max(0, _virtualTopRangeIndex);
			virtualTopRangeIndex = _virtualTopRangeIndex;
			virtualPlaceholderTopHeight.value = (_virtualTopRangeIndex / (option.value.virtualListCol as number)) * virtualCellHeight.value;
		}
		// 更新fixedCell模式下bottomRangeIndex&placeholderBottomHeight
		const _updateFixedBottomRangeIndex = (scrollIndex:number) => {
			let _virtualBottomRangeIndex = virtualCellHeight.value === 0 ? (option.value.virtualListPageSize as number) : scrollIndex + (parseInt(`${finalVirtualPageHeight.value / virtualCellHeight.value}`) || 1) * ((option.value.preloadPage as number) + 1);
			_virtualBottomRangeIndex *= (option.value.virtualListCol as number);
			_virtualBottomRangeIndex = Math.min(option.value.virtualListData!.length, _virtualBottomRangeIndex);
			virtualBottomRangeIndex = _virtualBottomRangeIndex;
			virtualPlaceholderBottomHeight.value = (option.value.virtualListData!.length - _virtualBottomRangeIndex) * virtualCellHeight.value / (option.value.virtualListCol as number);
			_updateVirtualList();
		}
		const updateVirtualList = (newVal:any[]) => {
			emit('update:virtualList', newVal);
			emit('virtualListChange', newVal);
		}
		// 更新virtualList
		const _updateVirtualList = () => {
			const shouldUpdateList = updateVirtualListFromDataChange || (lastVirtualTopRangeIndex !== virtualTopRangeIndex || lastVirtualBottomRangeIndex !== virtualBottomRangeIndex);
			if (shouldUpdateList) {
				updateVirtualListFromDataChange = false;
				lastVirtualTopRangeIndex =  virtualTopRangeIndex;
				lastVirtualBottomRangeIndex = virtualBottomRangeIndex;
				updateVirtualList((option.value.virtualListData!).slice(virtualTopRangeIndex, virtualBottomRangeIndex + 1))
				
			}
		}
		// 重置动态cell模式下的高度缓存数据、虚拟列表和滚动状态
		const _resetDynamicListState = (resetVirtualList = false) => {
			virtualHeightCacheList.value = [];
			if (resetVirtualList) {
				updateVirtualList([])
			}
			virtualTopRangeIndex = 0;
			virtualPlaceholderTopHeight.value = 0;
		}
		// 重置topRangeIndex和placeholderTopHeight
		const _resetTopRange = () => {
			virtualTopRangeIndex = 0;
			virtualPlaceholderTopHeight.value = 0;
			_updateVirtualList();
		}
		// 检测虚拟列表当前滚动位置，如发现滚动位置不正确则重新计算虚拟列表相关参数(为解决在App中可能出现的长时间进入后台后打开App白屏的问题)
		const _checkVirtualListScroll = () => {
			if (finalUseVirtualList.value) {
				nextTick(() => {
					getRect(ctx,'.zp-paging-touch-view').then(node => {
						const currentTop = node?.top || 0;
						if (!node || (currentTop === pagingOrgTop && virtualPlaceholderTopHeight.value !== 0)) {
							_updateVirtualScroll(0);
						}
					});
				})
			}
		}
	

	return {
		finalUseVirtualList,
		virtualCellHeight,
		virtualHeightCacheList,
		virtualPlaceholderTopHeight,
		virtualPlaceholderBottomHeight,
		_updateVirtualScroll,
		doInsertVirtualListItem,
		didUpdateVirtualListCell,
		didDeleteVirtualListCell,
		updateVirtualListRender,
		_virtualListInit,
		_checkVirtualListScroll,
	};
};

export default useVirtual;